//着色器变体切换 ，Keyword 工作流
//Shader.enableKeyword("xxx");      //全局
//mainMtr.enableKeyword("xxx");     //材质绑定

namespace FIREFLYX {
    /** 渲染加载模型 */
    export class ShaderKeywordDemo implements IExample {
        public async Init(canvas: HTMLCanvasElement) {
            const gl = canvas.getContext("webgl2");
            //app init
            App.init(gl.canvas as any);
            //简单观察相机
            const cVEnv = GenCamViewEnv();
            const cam = cVEnv.camera;
            cVEnv.camHover.distance = 20;

            //模型节点
            const model = new GameObject("model");
            model.transform.scale = new Vector3(2, 2, 2);
            model.transform.position = new Vector3(2, 0, 2);
            const mr = model.addComponent<MeshRenderer>(MeshRenderer);

            //资源准备
            const mesh = DefaultAsset.GetMesh(DefMesh.SPHERE);
            //纹理
            const tex = DefaultAsset.GetTexture(DefTexture.GRID);

            //加载 Unlit/colorTex shader
            const shUrl = `res/shaders/colorTex.shader.json`;
            const sh = await AssetManager.LoadFile(shUrl) as Shader;
            if (!sh.isLoadedAll()) await sh.loadAllFile();
            sh.apply();
            //-----shader enable keyword-------
            Shader.enableKeyword("RED");
            // sh.enableKeyword("GREEN");
            // sh.enableKeyword("BLUE");
            //disable keyword
            // sh.disableKeyword("RED");
            // sh.disableKeyword("GREEN");
            // sh.disableKeyword("BLUE");
            //---------------------------------

            //设置 renderer
            mr.mesh = mesh;
            const mainMtr = new Material();
            mr.materialGroup.push(mainMtr);
            //设置材质
            // mainMtr.shader = bSh;
            mainMtr.shader = sh;
            mainMtr.setProperty(`u_mainTex`, tex);

            //-----Material enable keyword-------
            // mainMtr.enableKeyword("RED");
            mainMtr.enableKeyword("GREEN");
            mainMtr.enableKeyword("BLUE");
            //disable keyword
            // mainMtr.disableKeyword("RED");
            mainMtr.disableKeyword("GREEN");
            // mainMtr.disableKeyword("BLUE");
            //---------------------------------

            //--------keyword 性能测试-------------
            //是否比较 新keyword 模式性能
            const isCompareNewKeywordPerformance = true;
            if (isCompareNewKeywordPerformance) {
                setTimeout(() => {
                    alert(`开始进行 Keyword 的性能测试 ，结果请按 F12 查看console 打印结果。`);
                    //比较 新keyword 模式性能
                    // this.compareNewKeywordModePerformance(10, 1000000);
                    // this.compareNewKeywordModePerformance(100, 1000000);
                    // this.compareNewKeywordModePerformance(1000, 1000000);
                    // this.compareNewKeywordModePerformance(10, 1000000);
                    // this.compareNewKeywordModePerformance(100, 1000000);
                    // this.compareNewKeywordModePerformance(1000, 1000000);
                    //
                    this.compareNewKeywordModePerformance(5, 10000);
                    this.compareNewKeywordModePerformance(10, 10000);
                    this.compareNewKeywordModePerformance(50, 10000);
                    this.compareNewKeywordModePerformance(100, 10000);
                    this.compareNewKeywordModePerformance(5, 1000000);
                    this.compareNewKeywordModePerformance(10, 1000000);
                    this.compareNewKeywordModePerformance(50, 1000000);
                    this.compareNewKeywordModePerformance(100, 1000000);

                }, 2000);
            }
            //-----------------------------------------
        }

        /** 比较 */
        private compareNewKeywordModePerformance(keysCount: number, loopCount: number) {
            let keys = [];
            keys.length = keysCount;
            for (let i = 0; i < keys.length; i++) { keys[i] = i; }

            let sh = new Shader();

            const keysLen = keys.length;
            const keysLenD = keysLen * 2;
            let time = 0;
            const deltaTime = () => {
                let time1 = Date.now();
                let defTime = time1 - time;
                time = time1;
                return defTime;
            };

            //random Vals 
            let randomVals: number[] = [];
            let randomCount = 10000;
            for (let i = 0; i < randomCount; i++) {
                randomVals.push(Math.random());
            }

            console.error(`----compareNewKeywordModePerformance keys Count ${keysCount} ， loop Count ${loopCount} `);

            deltaTime();
            {
                //new Keyword mode
                //  随机开关
                for (let i = 0; i < loopCount; i++) {
                    // let isEnable = Math.random() > 0.5;
                    // let ridx = Math.floor(Math.random() * keysLen);

                    let isEnable = randomVals[i % randomCount] > 0.5;
                    let ridx = Math.floor(randomVals[(i + 1) % randomCount] * keysLen);
                    let keyword = keys[ridx];
                    Shader.switchKeyword(`kw${keyword}`, isEnable);
                }
                console.error(`new Keyword mode use Time ${deltaTime()} , random`);

            }

            {
                //顺序开关
                for (let i = 0; i < loopCount; i++) {
                    // let isEnable = Math.random() > 0.5;
                    // let ridx = Math.floor(Math.random() * keysLen);
                    let isEnable = (i % keysLenD) > keysLen;
                    let ridx = i % keysLen;
                    let keyword = keys[ridx];
                    Shader.switchKeyword(`kw${keyword}`, isEnable);
                }

                console.error(`new Keyword mode use Time ${deltaTime()} , orderly`);
            }

            //old direct keyword mode
            let keywords: string[] = [];
            let keywordMap: Map<string, boolean> = new Map();
            let chainKey: string;
            {
                for (let i = 0; i < loopCount; i++) {
                    // let isEnable = Math.random() > 0.5;
                    // let ridx = Math.floor(Math.random() * keysLen);
                    let isEnable = randomVals[i % randomCount] > 0.5;
                    let ridx = Math.floor(randomVals[(i + 1) % randomCount] * keysLen);
                    let keyword = keys[ridx];
                    //
                    if (isEnable) {
                        //检查是否没有
                        if (keywordMap.has(keyword)) continue;
                        keywordMap.set(keyword, true);
                        //添加到列表 ，排序 ， 生成 chainKey
                        keywords.push(keyword);
                        keywords.sort();
                        chainKey = keywords.toString();
                    } else {
                        //检查是否已经有了
                        if (!keywordMap.has(keyword)) continue;
                        keywordMap.delete(keyword);
                        //添加到列表 ，排序 ， 生成 chainKey
                        let idx = keywords.indexOf(keyword);
                        keywords.splice(idx, 1);
                        keywords.sort();
                        chainKey = keywords.toString();
                    }
                }

                console.error(`old direct keyword mode use Time ${deltaTime()} , random`);
            }

            {
                //顺序开关
                for (let i = 0; i < loopCount; i++) {
                    let isEnable = (i % keysLenD) > keysLen;
                    let ridx = i % keysLen;
                    let keyword = keys[ridx];
                    //
                    if (isEnable) {
                        //检查是否没有
                        if (keywordMap.has(keyword)) continue;
                        keywordMap.set(keyword, true);
                        //添加到列表 ，排序 ， 生成 chainKey
                        keywords.push(keyword);
                        keywords.sort();
                        chainKey = keywords.toString();
                    } else {
                        //检查是否已经有了
                        if (!keywordMap.has(keyword)) continue;
                        keywordMap.delete(keyword);
                        //添加到列表 ，排序 ， 生成 chainKey
                        let idx = keywords.indexOf(keyword);
                        keywords.splice(idx, 1);
                        keywords.sort();
                        chainKey = keywords.toString();
                    }
                }

                console.error(`old direct keyword mode use Time ${deltaTime()} , orderly`);
            }
        }
    }
}